fix(deps): align @cipherstash/auth with its platform bindings (rc.2 B1)#679
Conversation
The rc.2 skilltester run found every project-local npm install of the
CLI/SDK dying at startup with "Failed to load native binding" (B1,
reproduced 5/5 surfaces). Root cause: Dependabot bumped the six
@cipherstash/auth-* catalog entries to 0.42.0 while @cipherstash/auth —
individually ignored in dependabot.yml — stayed 0.41.0. auth pins its
bindings as exact-version optional peerDependencies, so the skew makes
npm nest per-consumer binding copies that the hoisted auth package
cannot resolve.
Reproduced against the published rc.2 and verified fixed with aligned
versions (npm dedupes to one hoisted binding; auth loads):
npm i @cipherstash/stack@1.0.0-rc.2 @cipherstash/stack-supabase@1.0.0-rc.2
npm i -D stash@1.0.0-rc.2
node -e "require('@cipherstash/auth')" # fatal before, loads after
Three changes so it can't recur:
- catalog: all seven @cipherstash/auth* entries at 0.42.0, with the
lockstep invariant documented as load-bearing
- dependabot: ignore @cipherstash/auth-* alongside @cipherstash/auth —
partial bumps of this set are never safe
- supply-chain e2e: a test that fails on any version skew across the
seven entries (verified red against the exact rc.2 skew)
auth 0.42.0 compatibility verified: stack 828/828 (incl. live ZeroKMS
auth), cli 513/513, wizard 145/145.
Claude-Session: https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w
🦋 Changeset detectedLatest commit: c69e6b5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
📝 WalkthroughWalkthroughUpdates the auth workspace catalog to version 0.42.0, documents lockstep binding requirements, adds an end-to-end catalog consistency check, and records patch releases for related packages. ChangesAuth binding lockstep
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
freshtonic
left a comment
There was a problem hiding this comment.
Overview
Tightly-scoped fix for the rc.2 GA blocker (B1): @cipherstash/auth was catalog-pinned at 0.41.0 while its six @cipherstash/auth-* platform bindings sat at 0.42.0. Because auth declares those bindings as exact-version optional peer dependencies, the skew made npm nest per-consumer binding copies the hoisted auth package couldn't resolve — so every project-local CLI/SDK install died at startup with Failed to load native binding. The fix bumps auth to 0.42.0 (all seven now in lockstep), bars Dependabot from bumping any of them independently, and adds a CI guard so the skew can't recur.
The root-cause writeup and the reproduction are excellent, and the fix matches the diagnosis exactly.
What's right
- The core change is correct and minimal.
pnpm-workspace.yamlcatalog@cipherstash/auth: 0.41.0 → 0.42.0;pnpm-lock.yamlre-resolves cleanly to0.42.0(...bindings@0.42.0)across all three consumers (stack, cli, wizard). Verified all 7 catalog entries now read0.42.0. - The Dependabot guard is the right shape.
@cipherstash/auth-*correctly wildcard-matches the six bindings without over-matching@cipherstash/auth(listed separately) or unrelated scopes. A partial bump of this set is genuinely never safe, so ignoring the whole family and bumping manually is correct. - The e2e guard is well-designed. Asserting both
authEntries.length === 7andversions.size === 1means a future binding added/removed upstream trips the count assertion (forcing a deliberate update), while any version skew trips the set assertion — with a message that prints the offendingname@versionpairs. It reads the catalog (pnpm-workspace.yaml), which is the single source of truth since every consumer usescatalog:repo. This is the guard the "keep in lockstep" comment always implied but never enforced. - Docs/process hygiene: load-bearing rationale is now captured in three places (workspace comment, dependabot comment, test comment) rather than the old "for tidiness" framing; changeset present (patch for stack/stash/wizard); the durable upstream fix (auth declaring its bindings as its own
optionalDependencies, like the sibling@cipherstash/profileand@cipherstash/protect-ffi) is correctly identified as follow-up rather than attempted here.
Notes — minor, non-blocking
1. Unrelated lockfile churn — please confirm intentional. Beyond the auth lines, the pnpm-lock.yaml diff shifts a @vitest/mocker@3.2.7 peer resolution from @types/node@22.20.1 to @types/node@26.1.1 (and adds a matching snapshot block). It's benign — @types/node@26.1.1 already resolves 21× in the base lockfile, and this only touches a dev/test-only mocker peer, not any runtime dependency — but it's incidental to an auth-alignment PR and unexplained in the description. Worth a sentence confirming it's just re-resolution drift from regenerating the lock, so a reviewer doesn't have to reverse-engineer it.
2. (Optional) The guard covers the catalog, not the lockfile or consumer manifests. That's the correct primary check — the catalog is the source of truth and frozen-lockfile CI keeps the lock honest. No change needed; noting only so the guard's scope is explicit: it would not catch a hand-edited consumer optionalDependencies that bypassed catalog:repo, but nothing in-repo does that today.
Verdict
Correct, well-tested, and the regression guard closes the exact hole that produced the blocker — this is good to merge. The only ask is a one-line confirmation that the @types/node lockfile shuffle (item 1) is intentional re-resolution and not a stray change.
freshtonic
left a comment
There was a problem hiding this comment.
Approving — the fix is correct, minimal, and well-guarded, and it resolves the rc.2 GA blocker (B1). The catalog lockstep bump, the Dependabot @cipherstash/auth-* ignore, and the new supply-chain e2e guard together close exactly the hole that caused it. My earlier review has the detail; the only open item is the minor, non-blocking ask to confirm the unrelated @types/node lockfile re-resolution is intentional.
|
@freshtonic — confirmed intentional, and on inspection it's slightly better than re-resolution drift: it's pnpm repairing a stale cross-wiring in the existing lock. On i.e. the 26.1.1-flavoured vitest was borrowing the mocker keyed on the 22.20.1-flavoured vite — a leftover from whichever earlier partial re-resolution introduced the second flavour. Regenerating the lock for the auth bump made the 26.1.1 peer graph self-consistent (hence the new Dev/test-only ( |
|
Tracked by #718. |
What
Fixes the rc.2 GA blocker B1: every project-local npm install of the CLI or SDK dies at startup with
Failed to load native binding for <platform>(reproduced on 5/5 surfaces in the 2026-07-17 skilltester run).Root cause
@cipherstash/authpins its six platform bindings as exact-version optional peerDependencies. Our catalog compensates by declaring the bindings in stack/stash/wizard's ownoptionalDependencies— but Dependabot bumped those six entries to0.42.0(4164f18) while@cipherstash/authitself, individually ignored independabot.yml, stayed0.41.0. With the set skewed, npm nests per-consumer binding copies (node_modules/stash/node_modules/@cipherstash/auth-darwin-arm64) that the hoistedauthpackage can never resolve.Reproduced against the published rc.2 with the skilltester's exact sequence, and verified fixed with aligned versions (npm dedupes to one hoisted, resolvable binding):
Changes
@cipherstash/auth*entries move to0.42.0, with the lockstep invariant documented as load-bearing (not tidiness).@cipherstash/auth-*joins@cipherstash/authon the ignore list — a partial bump of this set is never safe.pnpm-workspace.yaml's "keep in lockstep" comment always needed.Changeset: patch for
@cipherstash/stack,stash,@cipherstash/wizard.Verification
0.42.0runtime compatibility: stack 828/828 (includes the live ZeroKMS suites, which authenticate through auth), cli 513/513, wizard 145/145. (searchable-json-pg.test.tsneedsDATABASE_URLand didn't run locally — unrelated to auth; covered in CI.)Upstream follow-up (cipherstash-suite)
The durable fix is for
@cipherstash/authto declare its bindings as its ownoptionalDependencies(the napi-rs default), so consumers never pin them at all — its sibling@cipherstash/profilein the same repo already does exactly this, as does@cipherstash/protect-ffi. Filing that separately; once auth ships it, the catalog binding entries here can be deleted entirely.https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w
Summary by CodeRabbit
Bug Fixes
Chores